import { expect } from 'chai';
import * as sinon from 'sinon';
import {getSAECertificate,Sae} from '../src/sae'
import Client,{DescribeChangeOrderResponseBodyData,DescribeChangeOrderResponseBodyDataPipelines} from '@alicloud/sae20190506'
import * as step from '@flow-step/step-toolkit'
import process from 'process'
import * as $OpenApi from '@alicloud/openapi-client'


export type RamStsCertificate = {
    accessKeyId: string,
    accessKeySecret: string
    securityToken: string
    accountId: string

}

describe('getSAECertificate', () => {
  let sandbox: sinon.SinonSandbox;
  let processEnv: NodeJS.ProcessEnv;
  let getRamStsCertificateStub: sinon.SinonStub;

  before(() => {
    sandbox = sinon.createSandbox();
    processEnv = process.env;
    getRamStsCertificateStub = sandbox.stub(step.certificate, 'getRamStsCertificate');
  });

  after(() => {
    sandbox.restore();
    process.env = processEnv;
  });

  beforeEach(() => {
    process.env.FLOW_JOB_TOKEN = 'mockFlowJobToken';
    process.env.SERVICE_CONNECTION_ID = 'mockConnectionId';
  });

  it('should return the certificate when all conditions are met', async () => {
    const mockCertificate: RamStsCertificate = {
      accessKeyId: 'mock_ak',
      accessKeySecret: 'mock_sk',
      securityToken: 'mock_sts',
      accountId: 'mock_id',
    };

    getRamStsCertificateStub.resolves(mockCertificate);

    const certificate = await getSAECertificate();

    sinon.assert.calledWith(getRamStsCertificateStub, 'mockFlowJobToken', 'mockConnectionId')
    expect(certificate).to.deep.equal(mockCertificate);
  });

  it('should throw an error if FLOW_JOB_TOKEN is not set', async () => {
    delete process.env.FLOW_JOB_TOKEN;

    try {
      await getSAECertificate();
      expect.fail('Expected an error to be thrown');
    } catch (error) {
      // @ts-ignore
        expect(error.message).to.equal('missing FLOW_JOB_TOKEN');
    }
  });

  it('should throw an error if getRamStsCertificate returns undefined', async () => {
    getRamStsCertificateStub.resolves(undefined);

    try {
      await getSAECertificate();
      expect.fail('Expected an error to be thrown');
    } catch (error) {
      // @ts-ignore
        expect(error.message).to.equal('get RamStsCertificate but error: undefined');
    }
  });

  it('should throw an error if getRamStsCertificate returns a certificate with an empty accessKeyId', async () => {
    const mockCertificate: RamStsCertificate = {
      accessKeyId: '',
      accessKeySecret: 'mock_sk',
      securityToken: 'mock_sts',
      accountId: 'mock_id',
    };

    getRamStsCertificateStub.resolves(mockCertificate);

    try {
      await getSAECertificate();
      expect.fail('Expected an error to be thrown');
    } catch (error) {
      // @ts-ignore
        expect(error.message).to.equal('get RamStsCertificate but error: {"accessKeyId":"","accessKeySecret":"mock_sk","securityToken":"mock_sts","accountId":"mock_id"}');
    }
  });
});




describe('getNextPipelineID', () => {
    const mockConfig = new $OpenApi.Config({
            endpoint: 'mock',
        }
    )
    const sae = new Sae(new Client(mockConfig))
  it('should return undefined if status is not 8', async () => {
    const changeOrderDetail = new DescribeChangeOrderResponseBodyData;
    changeOrderDetail.status = 1;

    const result = await sae.getNextPipelineID(changeOrderDetail);
    expect(result).to.be.undefined;
  });

  it('should return the first pipelineId with status 0', async () => {
      const changeOrderDetail = new DescribeChangeOrderResponseBodyData;
      changeOrderDetail.status = 8;

      const ppl1 = new DescribeChangeOrderResponseBodyDataPipelines;
      ppl1.status = 1;
      ppl1.pipelineId='ppl1'
      const ppl2 = new DescribeChangeOrderResponseBodyDataPipelines;
      ppl2.status = 0;
      ppl2.pipelineId='ppl2'

      changeOrderDetail.pipelines=[
          ppl1,
          ppl2
      ]


    const result = await sae.getNextPipelineID(changeOrderDetail);
    expect(result).to.equal('ppl2');
  });

  it('should return undefined if no pipeline has status 0', async () => {
      const changeOrderDetail = new DescribeChangeOrderResponseBodyData;
      changeOrderDetail.status = 8;

      const ppl1 = new DescribeChangeOrderResponseBodyDataPipelines;
      ppl1.status = 1;
      ppl1.pipelineId='ppl1'
      const ppl2 = new DescribeChangeOrderResponseBodyDataPipelines;
      ppl2.status = 1;
      ppl2.pipelineId='ppl2'

      changeOrderDetail.pipelines=[
          ppl1,
          ppl2
      ]

      const result = await sae.getNextPipelineID(changeOrderDetail);
      expect(result).to.be.undefined;
  });
});
